/**
 *
 gcc -Wall dict.c myregex.c regex.c ic.c -lm -Ddebug -DSTDC_HEADERS -liconv && a nude
 gcc -Wall dict.c myregex.c regex.c -lm -Ddebug -DSTDC_HEADERS -o ~/a && ~/a
 gcc -Wall dict.c myregex.c -Ddebug && ./a.out
 gcc -Wall dict.c -Ddebug && a fun
 > dict.txt
 * @file readall.c
 *  
 * @author db0@qq.com
 * @version 1.0.1
 * @date 2013-11-13
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "dict.h"
#include "myregex.h"

#define TRUE 1
/*
 * Struct to describe the idx file.
 */
typedef struct
{
	char word[100];//单词
	int offset;//
	int length;//
} WORD_IDX;
typedef struct
{
	char version[100];            //版本
	int wordcount;            //单词数量
	int idxfilesize;          //索引文件大小
	char bookname[100];           //词典名称
	char sametypesequence[10];
	char other_info[1000];    //其他不关心的信息
} DICT_INFO;
/*
 * Get a OFF_LEN struct of a word.
 */
static void *get_words(char *filename, DICT_INFO *dict_info, WORD_IDX *word_idx);
/*
 * Binary search for word's idx information.
 */
WORD_IDX *get_idx(char *word,WORD_IDX *word_idx, DICT_INFO *dict_info0);
inline static int to_int(unsigned char* from_int);

DICT_INFO dict_info;
WORD_IDX *idx;
FILE* dict_handle=NULL;
/*
 * read the index file,find all the words
 */
static void *get_words(char *filename, DICT_INFO *dict_info, WORD_IDX *word_idx)
{
	FILE *fd= fopen(filename,"rb");
	if(fd == NULL || dict_info == NULL)
		return NULL;
	/*printf("\ndict_info.fsize:%d:\n",dict_info->idxfilesize);*/
	static unsigned char buffer[1024*1024];//read the index file
	fread(buffer,dict_info->idxfilesize,1,fd);
	unsigned char *head,*tail;
	head=tail=buffer;
	int it=0;//cur pos;
	int total=1;//the len of word arr;
	for(; it < dict_info->idxfilesize; it++)
	{
		if(*head == '\0')//reach the end of the word
		{
			strncpy((char*)((word_idx+total)->word),(char*)tail,(size_t)(head-tail+1));//save the word to arr;
			(word_idx+total)->offset=to_int(head+1);//the offset of the word mean; 
			(word_idx+total)->length=to_int(head+5);//the length of the word mean;
			/*printf((word_idx+total)->word);*/
			/*printf((word_idx+total)->offset);*/
			/*printf((word_idx+total)->length);*/
			total++;
			head+=9;
			tail=head;
			if(total==dict_info->wordcount)break;//reach the end of file 
		}else{
			head++;
		}
	}
	return 0;
}

inline static int to_int(unsigned char *from_int)
{
	return *(from_int+3)+(*(from_int+2)<<8)+(*(from_int+1)<<16)+(*from_int<<24);
}

WORD_IDX *get_idx_contain(char *word,WORD_IDX *word_idx, DICT_INFO *dict_info)
{
	if(word == NULL || word_idx == NULL || dict_info == NULL)return NULL;
	//二分法查找
	int head=0,tail=dict_info->wordcount,cur=tail/2;
	while(TRUE)
	{
		int cmp=strncasecmp(word,word_idx[cur].word,strlen(word));
		if(0 == cmp)
		{
			return &word_idx[cur];
		}else if(0 > cmp){
			tail = cur-1;
		}else{
			head = cur+1;
		}
		cur=(tail+head)/2;
		if(tail<head){
			//printf("not exist----------------------------\n");
			return NULL;
		}
	}
	return NULL;
}

WORD_IDX *get_idx(char *word,WORD_IDX *word_idx, DICT_INFO *dict_info)
{
	if(word == NULL || word_idx == NULL || dict_info == NULL)return NULL;
	//二分法查找
	int head=0,tail=dict_info->wordcount,cur=tail/2;
	while(TRUE)
	{
		int cmp=strcasecmp(word,word_idx[cur].word);
		if(0 == cmp)
		{
			return &word_idx[cur];
		}else if(0 > cmp){
			tail = cur-1;
		}else{
			head = cur+1;
		}
		cur=(tail+head)/2;
		if(tail<head){
			WORD_IDX* retword = NULL;
			int _len = strlen(word);
			char*w = (char*)malloc(_len);
			sprintf(w,word);
			--_len;
			while(_len>0){
				w[_len] = '\0';
				//retword = get_idx_contain(w,word_idx,dict_info);
				retword = get_idx(w,word_idx,dict_info);
				if(retword)break;
				--_len;
			}
			free(w);
			if(retword){
				return retword;
			}
			printf("not exist----------------------------\n");
			return NULL;
		}
	}
	return NULL;
}


int open_dict(char *index_file,char *dict_file)
{
	dict_info.wordcount=39429;
	dict_info.idxfilesize=721264;

	idx = (WORD_IDX*)malloc(sizeof(WORD_IDX)*dict_info.wordcount);
	get_words(index_file,&dict_info,idx);

	dict_handle = fopen(dict_file,"r");
	if(dict_handle == NULL)
	{
		printf("open dict error\n");
		return 2;
	}

	return 0;
}

char *get_mean_by_index(int id){
	if(dict_handle==0){
		open_dict("oxford-gb.idx","oxford-gb.dict");
	}

	WORD_IDX *word = idx + id;
	if(word == NULL)
		return NULL;

	/*printf("word:%s,offset:%d,wordLength:%d\n",word->word,word->offset,word->length);*/
	printf("%s\r\n",word->word);
	fflush(stdout);


	rewind(dict_handle);
	if(0 != fseek(dict_handle,word->offset,SEEK_SET)){
		printf("seek word error\n");
		return NULL;
	}
	int len = word->length+1;
	char * explain = (char*)malloc(len);
	memset(explain,0,len);
	fread(explain,word->length,1,dict_handle);
	return explain;
}

char *getmeans(char* cur_word)
{
	if(dict_handle==0){
		open_dict("oxford-gb.idx","oxford-gb.dict");
	}

	WORD_IDX *word = get_idx(cur_word,idx,&dict_info);
	if(word == NULL)
		return NULL;
	printf("word:%s,offset:%d,wordLength:%d\n",word->word,word->offset,word->length);
	if(0 != fseek(dict_handle,word->offset,SEEK_SET)){
		printf("seek word error\n");
		return NULL;
	}
	int len = word->length+1;
	char * explain = (char*)malloc(len);
	memset(explain,0,len);
	len = fread(explain,1,word->length,dict_handle);
	printf("fread len:%d\n",len);

	/*char * gbkstr = (char*)my_iconv((const char*)explain,(const char*)"utf-8",(const char*)"gb2312"); free(explain); explain = gbkstr;*/
	return explain;
}
#ifdef debug
int main(int argc,char**argv)
{
	char* explain;
	open_dict("oxford-gb.idx","oxford-gb.dict");
	char * theword = "help";
	if(argc>1)
		theword = argv[1];
	explain = getmeans(theword);
	explain = regex_replace_all(explain,"([^a-zA-Z])( [\\*0-9]+ )","\\1\r\n\\2");

#ifdef WIN32
	explain = my_iconv(explain,"utf-8","gb2312");
	//printf("你好"); explain = my_iconv("你好","utf-8","gb2312"); 
#endif

	printf("explain:%s\n",explain);
	fflush(stdout);
	free(explain);
	int i =1;
	/*while(i < dict_info.wordcount)*/
	while(i < 10)
	{
		explain = regex_replace_all(get_mean_by_index(i)," \\* ","\r\n");
		printf("%s\r\n",explain);

		fflush(stdout);
		free(explain);
		++i;
	}
	/*getchar();*/
	return 0;
}
#endif
/**
 *
 * 
 */
